<script setup>

import moduleJson from "@/components/page/moduleJson"
import dataJson from "@/components/page/dataJson"
import {inject, nextTick, onMounted, reactive, ref, toRaw, toRefs, unref} from "vue";
import ImageClassificationModel from "@/model/ImageClassificationModel.js";
import {CloseBold, Delete, EditPen, Plus, Refresh} from "@element-plus/icons-vue";
import ImageClassificationService from "@/service/impl/ImageClassificationService.js";
import dialogJson from "@/components/dialog/dialogJson.js";
import ImageItemEdit from "@/components/iamge/ImageItemEdit.vue";
import FileUploadService from "@/service/impl/FileUploadService.js"
import Dialog from "@/components/dialog/Dialog.vue";
import ImageConfig from "@/components/iamge/ImageConfig.vue";
import ModelService from "@/service/impl/ModelService.js";


const t = inject('$t')
const message = inject('message')
const data = dataJson()
const module = moduleJson()
const imageClassificationModel = ref(new ImageClassificationModel())
const pageTable = ref()
const editImageItem = dialogJson()
const imageConfigDialog = dialogJson()
const classification = ref([])
const loading = ref(false)
const delList = ref([])
const delContr = ref(false)
const editItem = ref(null)
const model = ref(null)
const models = ref([])
const yoloConfig = ref(null)
const url = window.webConfig.apiUrl()
const allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
const testTrainingLoding = ref(false)
const testImageShow = ref(false)
const imageClasss = ref([])
const init = () => {
    module.value.dialog.show = false
    ImageClassificationService.list({}).then(res => {
        classification.value = res.data.classs
        imageClasss.value = res.data.imageClasss
        models.value = res.data.models
        yoloConfig.value = res.data.yoloConfig
    })
}
const editOpen = () => {
    const fun = {
        0: () => {
            imageClassificationModel.value = new ImageClassificationModel()
        },
        1: () => {
            let obj = imageClasss.value.find(item => item.id === imageClassificationModel.value.id)
            imageClassificationModel.value = JSON.parse(JSON.stringify(obj))
        }
    }
    imageClassificationModel.value?.id ? fun[1](init) : fun[0](init)
    module.value.dialog.show = true
    module.value.dialog.load = false
}
const editConfirm = () => {
    const fun = {
        0: (src) => {
            ImageClassificationService.add(imageClassificationModel.value).then(res => {
                src()
            })
        },
        1: (src) => {
            ImageClassificationService.edit(imageClassificationModel.value).then(res => {
                src()
            })
        }
    }
    imageClassificationModel.value?.id ? fun[1](init) : fun[0](init)
}
const delConfirm = () => {
    if (!imageClassificationModel.value?.id) {
        message.warning("没选择分类")
        return
    }
    ImageClassificationService.del(imageClassificationModel.value).then(res => {
        init()
        message.success("删除成功")
        imageClassificationModel.value = new ImageClassificationModel()
    })
}
const training = () => {
    if (!imageClassificationModel.value.id) {
        message.warning("请选择要训练的分类")
        return
    }
    imageConfigDialog.value.title = "设置参数"
    imageConfigDialog.value.width = "40%"
    imageConfigDialog.value.data = yoloConfig.value
    if(imageConfigDialog.value.data){
        imageConfigDialog.value.show = true
    }
}
const onTraining = () => {
    if (!imageClassificationModel.value.id) {
        message.warning("请选择要训练的分类")
        return
    }
    let t1 = imageClasss.value.find(item => item.id === imageClassificationModel.value.id);
    ImageClassificationService.imageTraining({
        id: t1.id,
        yoloConfig: imageConfigDialog.value.data,
        title: t1.title,
        tag: '图片',
        remark: imageConfigDialog.value.data.remark
    }).then(res => {
        imageConfigDialog.value.show = false
    })
}
const testTraining = () => {
    if(!model.value){
        message.warning("请选择模型")
        return
    }
    const input = document.createElement('input');
    input.type = 'file';
    input.accept = 'image/*';
    input.onchange = (event) => {
        const file = event.target.files[0];
        if (!file) {
            removeInput()
            return;
        }
        if (!allowedTypes.includes(file.type)) {
            message.warning('只能上传图片文件');
            removeInput()
            return;
        }
        testTrainingLoding.value = true
        // 这里可以添加上传逻辑，例如使用FormData和fetch或axios发送文件
        ImageClassificationService.testTraining({
            file: file,
            model: model.value
        }).then(res => {
            testImageShow.value = true
            testTrainingLoding.value = false
            let imageUrl = url + res.data
            nextTick(() => {
                let imageById = document.getElementById("test-image");
                let testImageContainer = document.getElementById("test-image-container")
                const parentWidth = testImageContainer.offsetWidth;
                const parentHeight = testImageContainer.offsetHeight;
                const img = new Image();
                img.onload = function() {
                    const widthRatio = parentWidth / this.naturalWidth;
                    const heightRatio = parentHeight / this.naturalHeight;
                    const scaleRatio = Math.min(widthRatio, heightRatio);
                    imageById.style.width = `${this.naturalWidth * scaleRatio - 50}px`;
                    imageById.style.height = `${this.naturalHeight * scaleRatio - 50}px`;
                };
                img.src = imageUrl;
                imageById.src = imageUrl
                removeInput()
            })

        }).catch(e => {
            removeInput()
            testTrainingLoding.value = false
        })
    };
    input.click();
}
const onDelModel = (remark) => {
    ModelService.modelDel({
        remark: remark,
        modelType: 3
    }).then(res => {
        init()
    }).catch(e => {

    })
}
const uploadSingleImage = (file, val) => {
    if (!allowedTypes.includes(file.type)) {
        message.warning('只能上传图片文件');
        return;
    }
    // 这里可以添加上传逻辑，例如使用FormData和fetch或axios发送文件
    FileUploadService.uploadStrategy({
        file: file,
        path: 'image/' + val.id,
        class: 'imageProxy',
        languageClassificationId: val.languageClassificationId,
        classificationId: val.id
    }).then(res => {
        message.success("上传成功")
        imageList(val.id)
        removeInput()
    })
    // console.log('Uploading single image:', file);
}
const uploadBatchImages = (files, val) => {
    const validFiles = Array.from(files).filter(file => allowedTypes.includes(file.type));
    if (validFiles.length === 0) {
        message.warning('没有有效的图片文件');
        return;
    }
    // 这里可以添加上传逻辑，例如使用FormData和fetch或axios发送文件
    FileUploadService.uploadStrategyBatch({
        files: files,
        path: 'image/' + val.id,
        class: 'imageProxy',
        languageClassificationId: val.languageClassificationId,
        classificationId: val.id
    }).then(res => {
        message.success("上传成功")
        imageList(val.id)
        removeInput()
    })
    // console.log('Uploading batch images:', validFiles);
}
const removeInput = () => {
    const inputElement = document.getElementById('input');
    const parentElement = inputElement.parentNode;
    parentElement.removeChild(inputElement);
}
const uploadImage = (type) => {
    const input = document.createElement('input');
    input.type = 'file';
    input.accept = 'image/*';
    let t1 = imageClasss.value.find(item => item.id === imageClassificationModel.value.id);
    if (!imageClassificationModel.value.id || !t1) {
        message.warning("请选择分类")
        return
    }
    if (type === 1) {
        input.onchange = (event) => {
            const file = event.target.files[0];
            if (file) {
                uploadSingleImage(file, t1);
            }
        };
    } else if (type === 2) {
        input.multiple = true;
        input.onchange = (event) => {
            const files = event.target.files;
            if (files.length > 0) {
                uploadBatchImages(files, t1);
            }
        };
    }
    input.click();
}
const imageList = (val) => {
    data.value.data.classificationId = val !== undefined ? val : null
    loading.value = true
    ImageClassificationService.imageList(data.value.source()).then(res => {
        data.value.init(res)
        loading.value = false
    }).catch(e => loading.value = false)
}
const onImageDelSwitch = () => {
    if (!imageClassificationModel.value.id) {
        return
    }
    if (delList.value.length < 1) {
        delContr.value = true
    } else {
        // 删除
        delContr.value = false
    }
}
const onImageEdit = (event, val) => {
    if (delContr.value) {
        return
    }
    editImageItem.value.data = val
    editItem.value.show()
    event.preventDefault();
}
const onImageDelConfirm = () => {
    ImageClassificationService.delImageItem(delList.value).then(res => {
        message.success("删除成功")
        imageList(imageClassificationModel.value.id)
        delContr.value = false
        delList.value = []
    })
}
const onImageDelCancel = () => {
    delContr.value = false
    delList.value = []
}
const onImageItemSave = (list) => {
    editImageItem.value.data.featuresConfig = list
    ImageClassificationService.editItemFeatures(editImageItem.value.data).then(res => {
        message.success("保存成功")
        imageList(imageClassificationModel.value.id)
        editItem.value.onClose()
    })
}
const onTestImageClose = () => {
    testImageShow.value = false
}
const onRefresh = () => {
    init()
    imageList(imageClassificationModel.value.id)
}
onMounted(() => {
    module.value.layout = {
        tableLeft: false,
        width: "0px",
        table: false,
    }
    module.value.page = false
    module.value.init(null, null,
        ImageClassificationService.url.del, null, null)
    module.value.operations.width = "200px"
    module.value.dialog.width = "40%"
    init()
})

</script>
<template>
    <Page
        @refresh="onRefresh"
        :data="data"
        :module="module"
        @edit-confirm="editConfirm"
        ref="pageTable"
    >
        <template #table>
            <el-row style="width: 100%;height: calc(100% - 60px);overflow-y: auto;gap: 5px;align-content: start" v-loading="loading">
                <el-card :body-style="{ padding: '0px' }" style="width: 200px;height: 180px" v-for="item in data.list"
                         @click="(e) => onImageEdit(e,item)" :key="item.imageUrl">
                    <el-checkbox-group v-model="delList">
                        <el-checkbox :value="item.imageUrl">
                            <el-badge is-dot :type="item.status === 10 ?  'danger' : 'success'"
                                      style="position: absolute;left: 0;top: 0">
                                <el-image style="width: 200px;height: 150px"
                                          :src="`${url}${item.imageUrl}`" lazy/>
                                <el-row style="padding: 5px;font-size: 14px">
                                    特征标记数量：{{ item.featuresNum }}
                                </el-row>
                            </el-badge>
                        </el-checkbox>
                    </el-checkbox-group>
                </el-card>
            </el-row>
            <el-pagination background @current-change="(val) => {
             data.current = val
             imageList(data.data.classificationId)
            }" layout="prev, pager, next" :total="data.total" :default-page-size="data.size" style="margin: auto" />
            <el-row class="test-image" id="test-image-container" v-if="testImageShow">
                <el-button style="position: absolute;top: 0;right: 0" type="primary"
                           :icon="CloseBold" @click="onTestImageClose"/>
                <img id="test-image" style="margin: auto"/>
            </el-row>
        </template>
        <template #table-left>
        </template>
        <template #operate-before>
            <el-button type="primary" :icon="imageClassificationModel.id?EditPen:Plus" style="margin-left: 12px"
                       @click="editOpen">
                {{ imageClassificationModel.id ? '编辑' : '添加' }}
            </el-button>
            <el-button type="primary" class="refresh" :icon="Refresh" @click="onRefresh">{{$t('btn.refresh')}}</el-button>
            <el-select v-model="imageClassificationModel.id" clearable style="width: 200px;margin:0 15px 0 15px"
                       @change="imageList">
                <el-option
                    v-for="item in imageClasss"
                    :key="item.id"
                    :label="item.title"
                    :value="item.id"
                />
            </el-select>
            <el-popconfirm title="确认要删除吗?" @confirm="delConfirm">
                <template #reference>
                    <el-button type="danger" :icon="Delete">
                        删除
                    </el-button>
                </template>
            </el-popconfirm>
        </template>
        <template #operate-after>
            <el-dropdown split-button type="primary" style="margin-right: 12px">
                上传图像
                <template #dropdown>
                    <el-dropdown-menu>
                        <el-dropdown-item @click="uploadImage(1)">单张上传</el-dropdown-item>
                        <el-dropdown-item @click="uploadImage(2)">批量上传</el-dropdown-item>
                    </el-dropdown-menu>
                </template>
            </el-dropdown>
            <el-button v-if="!delContr" type="warning" @click="onImageDelSwitch">开启删除</el-button>
            <el-popconfirm v-if="delContr" title="确认要删除吗?" @confirm="onImageDelConfirm"
                           @cancel="onImageDelCancel">
                <template #reference>
                    <el-button type="danger" :icon="Delete">
                        批量删除
                    </el-button>
                </template>
            </el-popconfirm>
            <el-button type="primary" @click="training">训练样本</el-button>
            <el-select v-model="model" placeholder="选择模型" style="width: 200px;margin: 15px">
                <el-option
                    v-for="item in models"
                    :key="item.remark"
                    :label="item.remark"
                    :value="item.remark"
                >
                    <span style="float: left">{{ item.remark }}</span>
                    <el-icon style="float: right;margin-top: 10px" @click.stop="onDelModel(item.remark)"><Delete /></el-icon>
                </el-option>
            </el-select>
            <el-button type="primary" :loading="testTrainingLoding" @click="testTraining">测试样本</el-button>
        </template>
        <template #table-column>
            <el-table-column type="selection" width="55"/>
            <el-table-column prop="className" :label="$t('classification.name')" width="150"/>
            <el-table-column prop="sentenceCount" :label="$t('classification.sampleNum')" width="100"/>
            <el-table-column :label="$t('classification.keywordDesc')" show-overflow-tooltip>
                <template #default="scope">
                    {{ scope.row.keywords.map(item => item.keyword + "->" + item.replies).join('; ') }}
                </template>
            </el-table-column>
        </template>
        <template #after-table-event="row">
        </template>
        <template #table-dialog>
            <el-form :rules="imageClassificationModel.rules" :label-width="110" :label-position="'left'"
                     :model="imageClassificationModel" style="width: 100%;padding: 5px">
                <el-form-item :label="$t('classification.name')" prop="name">
                    <el-select
                        v-model="imageClassificationModel.languageClassificationId"
                        clearable :disabled="imageClassificationModel?.id !== null"
                    >
                        <el-option
                            v-for="item in classification"
                            :key="item.id"
                            :label="item.className"
                            :value="item.id"
                        />
                    </el-select>
                </el-form-item>
                <el-form-item label="图像分类名称" prop="title">
                    <el-input v-model="imageClassificationModel.title" autocomplete="off"/>
                </el-form-item>
                <el-form-item label="图像限制宽度" prop="imageWidth">
                    <el-input :disabled="imageClassificationModel.id !== null"
                              v-model="imageClassificationModel.imageWidth" autocomplete="off"/>
                </el-form-item>
                <el-form-item label="图像限制高度" prop="imageHeight">
                    <el-input :disabled="imageClassificationModel.id !== null"
                              v-model="imageClassificationModel.imageHeight" autocomplete="off"/>
                </el-form-item>
            </el-form>
        </template>
        <template #table-search>

        </template>

    </Page>

    <image-config :imageConfigDialog="imageConfigDialog" :defaultConfig="yoloConfig" @onTraining="onTraining" :models="models"/>
    <image-item-edit ref="editItem" :edit-image-item="editImageItem" @onSave="onImageItemSave"/>
    <a id="downloadLink" style="display: none"/>
</template>

<style lang="scss" scoped>
.test-training {
    height: 300px;
    width: 100%;
}

.test-training-top {
    height: 240px;
    width: 100%;
    overflow-y: auto;
}

.test-training-bottom {
    width: 100%;
    height: auto;
}

:deep(.el-badge__content.is-dot) {
    top: 6px !important;
    right: 13px !important;
}

.demo-image__error .block {
    padding: 30px 0;
    text-align: center;
    border-right: solid 1px var(--el-border-color);
    display: inline-block;
    width: 49%;
    box-sizing: border-box;
    vertical-align: top;
}

:deep(.el-checkbox__input) {
    left: 2px;
    top: -7px;
}

.test-image {
    background-color: rgba(91, 91, 95, 0.2);
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 99;
}
</style>
